package ms.jacrim.framework;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;

import ms.jacrim.Constants;
import ms.jacrim.pddl.PddlProblem;
import ms.jacrim.pddl.PddlSolution;
import ms.spm.IAppContext;

public class SolutionGenerator {

	public enum Status {
		READY, PLANNING
	};
	
	public final IAppContext Context;
	public final Model Model;
	protected final Configuration Config;
	protected final MessageOutput StdOut;
	
	protected Status status;
	private String inputPddlFile;
	private Thread plannerThread;
	private String modelFile;
	
	public SolutionGenerator(IAppContext context, Model model) throws Exception {
		Context = context;
		Model = model;
		Config = context.getService(Configuration.class);
		
		if (Config == null)
			throw new Exception("Unable to query Configuration service in the context.");
		
		StdOut = context.getService(MessageOutput.class);
		if (StdOut == null)
			throw new Exception("Unable to query MessageOutput service in the context.");
	}
	
	public Status Status() {
		return status;
	}
	
	public synchronized void Status(Status value) {
		status = value;
	}
	
	public void startPlanner() throws Exception {

		modelFile = new File((String) Config.get("model_file")).getName();
		String tempFolder = Config.get("output_folder");
		
		int i = modelFile.lastIndexOf(".");
		inputPddlFile = tempFolder + "\\" + modelFile.substring(0, i) + "-auto.pddl";

		PddlProblem p = Model.PddlModel.generatePddl();
		p.writeToFile(inputPddlFile);
		
		Status(Status.PLANNING);
		
		plannerThread = new Thread(new Runnable() {
			@Override
			public void run() {
				runPlanner();
			}
		});
		plannerThread.start();
	}

	private void runPlanner() {
		try {

			Status(Status.PLANNING);

			String command = Config.get("planner");
			int maxSolution = Config.get("max_solution");

			String arg = String.format("%s %s %s %d ", command, modelFile, inputPddlFile, maxSolution);

			StdOut.write(null, arg + "\r\n");

			ProcessBuilder b = new ProcessBuilder(Constants.CMD_PATH, "/C", arg);

			b.redirectErrorStream(true);
			Process lpg = b.start();

			// process output
			InputStream is = lpg.getInputStream();
			InputStreamReader isr = new InputStreamReader(is);
			BufferedReader br = new BufferedReader(isr);
			String line;
			while ((line = br.readLine()) != null)
				// StdOut.write(line + "\r\n")
				;

			StdOut.write(null, "Planner completed at %s.\r\n", new Date());

			Status(Status.READY);

		} catch (Exception e) {
			e.printStackTrace();
			Status(Status.READY);
		}
	}
	
	public void stopPlanner() {
		if (plannerThread != null)
			plannerThread.interrupt();
		plannerThread = null;
	}

	public PddlSolution getSolution(int index) {
		PddlSolution result = null;
		String filename = inputPddlFile + "_" + index + ".SOL";
		if (new File(filename).exists())
			try {
				result = new PddlSolution(null, filename);
			} catch (FileNotFoundException e) {
			}
		return result;
	}
	
	public int AvailableSolution() {
		int result = 0;
		for (int sol = 1;; sol++) {
			String filename = inputPddlFile + "_" + sol + ".SOL";
			if (new File(filename).exists())
				result++;
			else
				break;
		}
		return result;
	}

}
